#!/bin/ash
#(c) copyright Barry Kauler 2008, puppylinux.com
#2008 Lesser GPL licence v2 (http://www.fsf.org/licensing/licenses/lgpl.html)
# see also initNEW -> /sbin/init, init (initramfs), rc.shutdown.
#
# How rc.sysinit is triggered:
# - /sbin/init executes busybox init or minit
# - busybox init is controlled by /etc/inittab
#   /etc/inittab: rc.sysinit is specified as ::sysinit:
# - also read /etc/inittab.README
#
# eudev is enforced - min 151 - 175+ recommended
#
#w004 LANG=C, faster. /bin/ash, even faster.
#w481 fix crappy depmod, 'out of memory' in first boot 64MB RAM (no swap).
#v424 fix secondary uevent replay. now finds ssb devices.
#100131 bugfix detect multiple cd/dvd drives.
#100703 load fbcon module: needed by some xorg drivers when exit to console (ex: nouveau).
#100814 record cumulative tx/rx, see also network_tray and rc.shutdown.
#101119 /sbin/pup_event_backend_modprobe has been rewritten, repercussions here.
#101210 new path /tmp/pup_event_backend for files logged by /sbin/pup_event_backend_*.
#110405 fix 'free' applet output format different in later versions of busybox.
#110426 move done/failed/backgrounded 2 places to right (also in init script).
#110502 fix creation of owner:group for device nodes. 110503 fix permission fsckme.flg.
#110511 2nd uevent replay: now using udevadm for usb, ssb and pcmcia.
#110513 rcrsn51: udevadm usb replay fix, properly detect scanners etc.
#110712 fixes for kernel with usb core (including usb-storage) drivers builtin.
#110814 kernel with inbuilt usb drivers, usbfs was not mounting on /proc/bus/usb.
#120217 improvement for full hd install, non-english.
#120301 need to load console font earlier.
#120301 a problem if initrd has kernel default font, switching here changes all o/p from initrd to partial garbage.
#120313 fix 120301 font garbage. 120331 clear requires redirection to /dev/console.
#120423 pemasu: /dev/mouse was missing in full install.
#120503 if kernel mounts a f.s. on /dev, removes my skeleton /dev
#120709 BOOT_UDEVDCHILDREN from /etc/rc.d/BOOTCONSTRAINED
#120716 log size of ram, read by /sbin/initNEW for f.s. check.
#120717 log ext2,3,4 f.s. that have reached maximal mount count.
#130311 use modinfo to test if fbcon builtin.
#130504 moved up, i think fbcon needs to be loaded before intel, nouveau modules load.
#160609 rerwin: Add wait for USB3 driver.

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/X11R7/bin
. /etc/rc.d/functions_x

#================================================================
#              functions used by the script
#================================================================

status_func() {
 if [ $1 -eq 0 ];then
  echo -n -e "\\033[74G\\033[1;32m" >/dev/console #green [done] msg. 110426: change 72 to 74.
  echo -n "done" >/dev/console #done
  echo -e "\\033[0;39m" >/dev/console
 else
  echo -n -e "\\033[72G\\033[1;31m" >/dev/console #red [failed]. 110426: change 70 to 72.
  echo -n "failed" >/dev/console #failed
  echo -e "\\033[0;39m" >/dev/console
  STATUS=0
 fi
 return $1 #return with same status as entry param.
}

loadswap_func() { #w481 made into a function.
 echo "LOAD SWAP"
 #load a swap partition...
 for ONESWAP in `fdisk -l | grep ' Linux swap' | cut -f 1 -d ' ' | tr '\n' ' '`
 do
  SWAPSIZEBYTES=`fdisk -l $ONESWAP | grep -m1 $ONESWAP | cut -f 5 -d ' '` #bytes
  [ $SWAPSIZEBYTES ] && EXTRAALLOCK=$(($EXTRAALLOCK + $SWAPSIZEBYTES))
  echo -n "Loading swap partition $ONESWAP ("$(fx_format_bytes $SWAPSIZEBYTES)")..." >/dev/console #loading swap partition
  chmod 0660 $ONESWAP
  swapon $ONESWAP
  status_func $?
  [ $? -eq 0 ] && SWAPON="yes"
 done
 [ "$SWAPON" = "yes" ] && return
 #if no go, try for a swap file...
 pupswap validate /initrd${PUP_HOME}/pupswap.swp && SWF="/initrd${PUP_HOME}/pupswap.swp"
 pupswap validate /pupswap.swp && SWF="$SWF /pupswap.swp"
 for SWAPFILE in $SWF ; do
  SWAPSIZEBYTES=`stat -c %s ${SWAPFILE}` #bytes
  [ $SWAPSIZEBYTES ] && EXTRAALLOCK=$(($EXTRAALLOCK + $SWAPSIZEBYTES))
  echo -n "Loading swap file ${SWAPFILE} ("$(fx_format_bytes $SWAPSIZEBYTES)")..." >/dev/console
  chmod 0660 $SWAPFILE
  swapon ${SWAPFILE}
  status_func $?
  [ $? -eq 0 ] && SWAPON="yes"
 done
}

#global $MODULE is name of module, global $KERNVER.
firmware_tarball_func() {
 MODULEx="`echo -n "$MODULE" | tr '_' '-'`"
#121004 ... 
 fPATTERN='[:,]'"${MODULE}"'\.ko|[:,]'"${MODULEx}"'\.ko'
 FIRMPKG="`cat /etc/modules/firmware.dep.${KERNVER}  | grep -v '^#' | grep ':' | grep -E "$fPATTERN" | cut -f 1 -d ':' | head -n 1`"
 if [ "$FIRMPKG" != "" ];then
  iPATTERN='^'"${FIRMPKG}"'$'
  if [ "`grep "$iPATTERN" /etc/modules/firmware.dep.inst.${KERNVER}`" = "" ];then
   #120831 rerwin: ...
   FLAGFIRM='no'
   if [ -d /lib/modules/all-firmware/${FIRMPKG} ];then #support firmware directories.
    cp -a -f --remove-destination /lib/modules/all-firmware/${FIRMPKG}/* /
    FLAGFIRM='yes'
   else
    if [ -f /lib/modules/all-firmware/${FIRMPKG}.tar.gz ];then
     tar -z -x --strip=1 --directory=/ -f /lib/modules/all-firmware/${FIRMPKG}.tar.gz > /dev/null 2>&1
     FLAGFIRM='yes'
    fi
   fi
   if [ "$FLAGFIRM" = "yes" ];then #120831 end
    #execute any post-install script...
    if [ -f /pinstall.${FIRMPKG}.sh ];then
     BRKCNT=0; SLEEPU=$((${$} * 10))
     while [ 1 ];do #serialise execution of pinstall scripts...
      PINSTALLCNT=`find / -maxdepth 1 -type f -name 'pinstall.*.sh' | wc -l`
      [ $PINSTALLCNT -eq 1 ] && break
      usleep $SLEEPU
      BRKCNT=$(($BRKCNT + 1))
      [ $BRKCNT -gt 5 ] && break
     done
     #120828 remove...
     #echo "$MODULE" >> /etc/modules/firmware.dep.inst.${KERNVER}
     cd /
     /pinstall.${FIRMPKG}.sh >/dev/null 2>&1
     rm -f /pinstall.${FIRMPKG}.sh >/dev/null 2>&1
    fi
    echo "$FIRMPKG" >> /etc/modules/firmware.dep.inst.${KERNVER} #120828
   fi
  fi
 fi
}

#================================================================
#                         MAIN
#================================================================
# mount devtmpfs early
mount -t devtmpfs devtmpfs /dev 2>/dev/null

#if have just done a switch_root, output a 'done' message...
[ -d /initrd ] && status_func 0

ORIGLANG="`grep '^LANG=' /etc/profile | cut -f 2 -d '=' | cut -f 1 -d ' '`" #120217
ORIGLANG1="${ORIGLANG%_*}" #ex: en
export LANG=C

. /etc/DISTRO_SPECS
. /etc/rc.d/BOOTCONSTRAINED # has BOOT_DISABLESWAP, BOOT_ATIME, BOOT_DIRTYWRITE.
. /etc/rc.d/MODULESCONFIG #modules loading configuration.
[ $loglevel ] && LOGLEVEL=$loglevel #boot param.
[ $pmedia ] && PMEDIA=$pmedia #boot parameter, broad category of boot media. ex: cd.
[ $pdev1 ] && PDEV1=$pdev1    #boot parameter, partition have booted off. ex: hda3

#120301 a problem if initrd has kernel default font, switching here changes all o/p from initrd to partial garbage.
#workaround, clear the screen...
if [ -d /initrd ];then #120313 fix...
 PLANG1=`grep '^PLANG=' /etc/rc.d/PUPSTATE | cut -f 2 -d '=' | cut -f 1 -d '_'`
 [ ! "$PLANG1" ] && PLANG1='en'
 [ "$ORIGLANG1" != "$PLANG1" ] && clear > /dev/console #120331 redirection is required.
fi
load_consolefont #120301 if this was done in initrd then it would carry through, and this would not be needed.
#...this is done in rc.country, but needs to be move above all the o/p to /dev/console.

STATUS=0

##############MAKE FILESYSTEM USABLE################

echo -n "Making the filesystem usable..." >/dev/console

# mount /proc before remounting / as rw (full install)
mount -t proc none /proc 2>/dev/null; STATUS=$((STATUS+$?))

FREERAM=`free | grep -o 'Mem: .*' | tr -s ' ' | cut -f 4 -d ' '` #w481 110405
QTRFREERAM=`expr $FREERAM \/ 4`

# full-hd-install
if [ ! -d /initrd ];then
 BDEV="$(df | grep '^/dev/' | grep ' /$')"; BDEV=${BDEV%% *}
 if [ "$BOOT_ATIME" ];then # see /etc/rc.d/BOOTCONSTRAINED, variable set in 3builddistro.
  mount -o remount,rw,${BOOT_ATIME} / 2>/dev/null #have set this to 'relatime'.
  [ $? -eq 0 ] || mount -o remount,rw,${BOOT_ATIME} $BDEV / #have set this to 'relatime'.
 else
  mount -o remount,rw / 2>/dev/null
  [ $? -eq 0 ] || mount -o remount,rw $BDEV /
 fi
 #no longer deleting /tmp/* in rc.shutdown... (note, init script in initrd.gz wipes it)
 rm -rf /tmp/*
 rm -rf /tmp/.[0-9a-zA-Z]*
 #tmpfs on /tmp for full HD installation
 #120717 this is not so good on raspi with only 256MB RAM, but saves flash writes and faster...
 mount -t tmpfs -o size=${QTRFREERAM}k tmpfs /tmp ;STATUS=$((STATUS+$?))
 chmod 1777 /tmp 2>/dev/null
 #120716 /sbin/init needs to know ramdisk size, before /sys mounted...
 [ ! -f /var/local/ram_size_bytes ] && [ -e /sys/block/ram0/size ] && cat /sys/block/ram0/size > /var/local/ram_size_bytes
 #120717 log maximal mount counts, potentially rc.shutdown can then not delete /fsckme.flg...
 #dmesg | grep -o 'EXT[2,3,4]-fs.*running e2fsck is recommended' > /tmp/dmesg_e2fsck_warnings1
 dmesg | grep -o 'EXT[2,3,4]-fs.*maximal mount count reached' > /tmp/dmesg_e2fsck_warnings1
 #example lines:
 #EXT3-fs (sda9): warning: mounting fs with errors, running e2fsck is recommended
 #EXT3-fs (sda10): warning: maximal mount count reached, running e2fsck is recommended
 #--
 #write to PUPSTATE after remount r/w.
 if [ ! -f /var/tmp/initrd_full_install_flag ] ; then
   echo 'PUPMODE=2' > /etc/rc.d/PUPSTATE
   if [ "$ORIGLANG1" != "en" ];then #120217
    echo "OUTPUT_CHARSET=UTF-8
export OUTPUT_CHARSET" >> /etc/rc.d/PUPSTATE
   fi
 fi
fi
. /etc/rc.d/PUPSTATE #variables created at bootup by init script in initrd.

if [ "$BOOT_DIRTYWRITE" ];then #120704 see /etc/rc.d/BOOTCONSTRAINED, variable set in 3builddistro.
 #i have set this as 1500 which is 15 seconds (default is 5 seconds).
 echo $BOOT_DIRTYWRITE > /proc/sys/vm/dirty_writeback_centisecs #refer: http://www.lesswatts.org/tips/disks.php
fi

#redirect all output to a log file (must do after remount rw)...
[ ! "$LOGLEVEL" ] && exec 1>/tmp/bootsysinit.log 2>&1

#mount/umount scripts no longer write to /etc/mtab, as gparted failed to create a
#gparted create ext3 part. failed, fixed by making /etc/mtab a symlink.
rm -f /etc/mtab
ln -sv /proc/mounts /etc/mtab

#120503 if kernel mounts a f.s. on /dev, removes my skeleton /dev
mkdir -p /dev/pts
mount -t devpts -o dev,suid,gid=2,mode=620 none /dev/pts ;STATUS=$((STATUS+$?))

mkdir /sys 2>/dev/null
mount -t sysfs none /sys ;STATUS=$((STATUS+$?))

##v2.20 some apps need shm (shared memory) (ex: xfdiff)... 100319 do this always...
mkdir -p /dev/shm #120503 if kernel mounts a f.s. on /dev, removes my skeleton /dev
mount -t tmpfs -o size=${QTRFREERAM}k shmfs /dev/shm ;STATUS=$((STATUS+$?))

# kernel modules.builtin/order can also be found in /etc/modules
# if somehow they're missing from /lib/modules, they will be copied back
KERNVER="`uname -r`"
[ ! -f /lib/modules/${KERNVER}/modules.builtin ] && \
	cp -v /etc/modules/modules.builtin-${KERNVER} /lib/modules/${KERNVER}/modules.builtin
[ ! -f /lib/modules/${KERNVER}/modules.order ] && \
	cp -v /etc/modules/modules.order-${KERNVER} /lib/modules/${KERNVER}/modules.order

#may need to run 'depmod'...
#live-cd may have been built without the modules.* files.
#initrd init script copied modules to /lib/modules/<kernver>/initrd/.
if [ ! -f /lib/modules/${KERNVER}/modules.dep ];then
 NEEDDEPMOD="yes" #files may not be there to save space.
 [ -d /lib/modules/${KERNVER}/initrd ] && NEEDGUNZIP="yes"
elif [ -d /lib/modules/${KERNVER}/initrd ];then
  #remove leading '/' from '/initrd/' for comaptibility with depmod-FULL...
  if [ "`cat /lib/modules/${KERNVER}/modules.dep | cut -f 1 -d ':' | grep  'initrd/'`" = "" ];then
   NEEDDEPMOD="yes" #files may not be there to save space.
   NEEDGUNZIP="yes"
  fi
fi
if [ "$NEEDGUNZIP" = "yes" ];then
 gunzip -f -r /lib/modules/${KERNVER}/initrd #shinobar.
fi

if [ "$NEEDDEPMOD" = "yes" ];then
 echo -n ' depmod' >/dev/console
 depmod
fi
status_func $STATUS

mount -a #Load fstab entries

## process some specific kernel params here
for i in $(cat /proc/cmdline) ; do
	case $i in
		inteluxa|intel_uxa|uxa) xorg_intel_uxa.sh ;;
	esac
done

######################LOAD SWAP#####################
[ "$BOOT_DISABLESWAP" ] && SWAPON="$BOOT_DISABLESWAP" #120704 now ask in 3builddistro if want use swap file/partition. anything not "yes" means no.
EXTRAALLOCK=0
[ "$SWAPON" != "yes" ] && loadswap_func
if [ "$SWAPON" = "yes" ];then
 # resize tmpfs
 # this code is meant to increase the size of the tmpfs
 # taking into account swap space and sfs_ram_sizek[might be removed]
 EXTRAALLOCK=$(($EXTRAALLOCK / 2048)) #use half in KiB
 RAMSIZE=$(free | grep -o 'Mem: .*' | tr -s ' ' | cut -f 2 -d ' ')
 FREEK=$(($RAMSIZE / 2)) #half of physical.
 ALLOCK=$(($FREEK + $EXTRAALLOCK))
 if [ "$(grep '/initrd/mnt/tmpfs' /proc/mounts)" != "" ];then #mounted
  [ -s /initrd/tmp/sfs_ram_sizek ] && ALLOCK=$(($ALLOCK + $(cat /initrd/tmp/sfs_ram_sizek))) #proper size
  mount -t tmpfs -o remount,size=${ALLOCK}k tmpfs /initrd/mnt/tmpfs
 elif [ ! -d /initrd ];then #full-install
  mount -t tmpfs -o remount,size=${ALLOCK}k tmpfs /tmp
 fi
fi

# Setup /mnt/home symlink before sfs_load
rm -f /mnt/home 2>/dev/null
if [ ! -d /initrd ];then
 PUP_HOME='/'
 [ ! -f /var/tmp/initrd_full_install_flag ] && echo "PUP_HOME='/'" >> /etc/rc.d/PUPSTATE
 ln -sv / /mnt/home
else
 if [ "$PUP_HOME" ];then #see /etc/rc.d/PUPSTATE
  if [ "$PUP_HOME" = "/pup_ro1" -o "$PUP_HOME" = "/pup_rw" ];then
   [ ! -d "$PUP_HOME" ] && echo "ERROR: $PUP_HOME does not exist"
   #note, PUPMODE=6 will have PUP_HOME=/pup_rw.
   #in the case of the persistent storage being the partition itself, this will be mounted
   #on /initrd/pup_ro1 (tmpfs on pup_rw for restricted writes) or directly on /initrd/pup_rw
   #and we do not really want users to access it as it is an aufs layer. Instead, they are
   #already accessing it as "/".
   ln -sv / /mnt/home
  else
   [ ! -d "/initrd${PUP_HOME}" ] && echo "ERROR: $PUP_HOME does not exist"
   ln -sv /initrd${PUP_HOME} /mnt/home
  fi
 fi
fi

#------ load extra sfs's if any ------
[ -d /initrd ] && sfs_load --cli start
#-------------------------------------

#######################VERSION UPDATE##########################
echo "VERSION UPDATE"
# rc.update determines what is to be updated according to $PUMODE
/etc/rc.d/rc.update $PUPMODE
status_func $STATUS

#ensure unique hostname: http://www.murga-linux.com/puppy/viewtopic.php?p=550932#550932
if [ "`cat /etc/hostname`" = "puppypc" ];then
 echo -n "Updating unique hostname..." >/dev/console #hostname
 echo "puppypc${RANDOM}" > /etc/hostname
 PUPHOSTNAME="`cat /etc/hostname`"
 HOSTSFILEFIRST="`grep -w 'puppypc' /etc/hosts|sed 's% puppypc%%'`"
 HOSTSFILEREST="`grep -v 'puppypc' /etc/hosts`"
 echo "$HOSTSFILEFIRST $PUPHOSTNAME" > /etc/hosts
 echo "$HOSTSFILEREST" >> /etc/hosts
 status_func 0
fi

#Ensure kernel-specific firmware.dep file present.
[ ! -e /etc/modules/firmware.dep.$KERNVER -a -f /etc/modules/firmware.dep ] \
 && cp -fv /etc/modules/firmware.dep /etc/modules/firmware.dep.$KERNVER

#################LOAD KERNEL MODULES################
echo "LOAD KERNEL MODULES"
echo -n "Loading kernel modules..." >/dev/console

MODALIASES="`ls /sys/bus/*/devices/*/modalias`"

#101119 new /sbin/pup_event_backend_modprobe, these must be deleted every boot...
rm -f /etc/modprobe.d/alsa_card*.conf 2>/dev/null
touch /etc/modules/firmware.dep.inst.${KERNVER} #make sure exists.
rm -f /dev/ttyUSB* 2>/dev/null #101210 may have been left there if modem plugged in at shutdown.
rm -f /dev/mixer 2>/dev/null #see test in /etc/init.d/10alsa.
rm -f /dev/snd/* #after a reboot, some of these may be wrong.
mkdir /tmp/rc_sysinit #101210 for logging into.
mkdir /tmp/pup_event_backend #101210 for logging into, see /sbin/pup_event_backend_modprobe.
mkdir /tmp/simple_network_setup #sns

#101119 no longer using /tmp/pup_event_modprobe.conf, put blacklist into /etc/modprobe.d/...
rm -f /etc/modprobe.d/blacklist*.conf
BLACKLISTVARS="`echo "$SKIPLIST" | tr '\-' '_' | tr ' ' '\n' | sed -e 's/^/blacklist /' | grep -v ' $'`"
echo "$BLACKLISTVARS" > /etc/modprobe.d/blacklist.conf

if [ ! -d /initrd ];then #full hd install.
 #one config of 2.6.33 has base floppy and ps/2 mouse support not builtin. have this in 'init' also...
 [ "`modinfo floppy 2>/dev/null`" != "" ] && modprobe floppy > /dev/null 2>&1
 [ "`modinfo psmouse 2>/dev/null`" != "" ] && modprobe psmouse
 #have this in 'init', probably need here too...
 if [ "`echo "$MODALIASES" | grep 'bc0Csc03i10'`" != "" ];then
  modprobe yenta-socket #101119
  [ $? -eq 0 ] && sleep 2
 fi
 # k2.6.29.6 dmesg has warning that ehci-hcd should load before uhci-hcd and ohci-hid
 # this is contrary to my understanding all these years, but oh well, let's do it...
 [ "`lspci -n | grep ' 0c03: '`" != "" ] && modprobe ehci-hcd > /dev/null 2>&1 #110712 maybe builtin to kernel.
 #...perhaps a udev rule could have done this?
fi

#130504 moved up, i think fbcon needs to be loaded before intel, nouveau modules load...
#101119 i really only want to load this for a kms-enabled video...
KMS=no
[ "`cat /proc/cmdline | grep 'modeset=1'`" != "" ] && KMS=yes
[ "`cat /etc/modprobe.d/* | grep '^options .* modeset=1'`" != "" ] && KMS=yes
[ "$KMS" = "yes" ] && [ "`modinfo fbcon 2>/dev/null`" != "" ] && modprobe fbcon #100703 needed by some xorg drivers when exit to console (ex: nouveau). 110712 maybe builtin. 130311 maybe builtin.

#130618 devtmpfs-enabled kernel, initrd may have loaded it on /dev
#device nodes created by kernel in initrd are all 'root' group.
#fix (before starting udevd)...
chmod 666 /dev/* 2>/dev/null
chmod 666 /dev/pts/* 2>/dev/null
chown -R root:tty /dev/pts/
chmod 666 /dev/null
chmod 666 /dev/zero
chmod 666 /dev/[pt]ty*
chmod 666 /dev/ptmx
chmod 777 /dev/pts/
chgrp tty /dev/[pt]ty*
chown -R root:tty /dev/pts/
chown root:tty /dev/tty1
chown root:tty /dev/ptmx
chgrp tty /dev/console #bugfix 140617
chgrp video /dev/fb0
chgrp floppy /dev/fd[0-9] 2>/dev/null
chgrp disk /dev/[hs]d[a-z]* 2>/dev/null
chgrp disk /dev/fuse
chgrp disk /dev/mmcblk* 2>/dev/null
chgrp disk /dev/nvme* 2>/dev/null
chgrp cdrom /dev/sr[0-9] 2>/dev/null
chmod 666 /dev/usb/* #rcrsn51 finally added 140618
chmod -R 1777 /dev/shm #SFR .. ditto
chmod 666 /dev/urandom #and again

rm -f /etc/init.d/udev #just in case
# UDEV_LOG=2 to prevent non-critical o/p to screen at bootup and shutdown...
#110502 change 'never' to 'early', fixes device nodes created with correct owner:group...
if [ "$BOOT_UDEVDCHILDREN" ];then #120709
   UDEV_LOG=2 udevd --daemon --resolve-names=early --children-max=${BOOT_UDEVDCHILDREN} #BOOT_UDEVDCHILDREN=1 good idea?
else
   UDEV_LOG=2 udevd --daemon --resolve-names=early
fi
sleep 0.1

#replay uevents from /sys...
for ONEMODALIAS in $MODALIASES
do
 ONEPATH="`dirname $ONEMODALIAS`"
 if [ -e ${ONEPATH}/uevent ];then
  echo add > ${ONEPATH}/uevent #generates an 'add' uevent.
  sleep 0.02
 fi
done

if [ ! -d /initrd ];then #full hd installation.
 modprobe nls_cp437 > /dev/null 2>&1 #these needed by vfat/ntfs/ext2 f.s.'s. 110712 maybe builtin.
 modprobe nls_iso8859-1 > /dev/null 2>&1 # "
 modprobe fuse 2>/dev/null
 modprobe aufs 2>/dev/null
 modprobe squashfs  2>/dev/null
 if [ ! -f /var/tmp/initrd_full_install_flag ] ; then
   #we can determine ide/sata drives at this point (drivers builtin to kernel)...
   #define ATADRIVES as all internal ide/pata/sata drives (not usb), except optical...
   #110712 rewritten to handle kernel with usb driver built-in...
   ALLDRVS0="`find /sys/block -maxdepth 1 -name 'mmc*' -o -name 'sd*' -o -name 'sr*' -o -name 'nvme*' | xargs -l readlink 2>/dev/null | grep -v '/usb[0-9]' | rev | cut -f 1 -d '/' | rev`" #all *except* usb!
   ALLDRVS="`echo "$ALLDRVS0" | tr '\n' ' '`" #all *except* usb!
   [ "$ALLDRVS" = " " ] && ALLDRVS=""
   ATADRIVES="`echo "$ALLDRVS0" | grep -v '^sr' | tr '\n' ' '`"
   [ "$ATADRIVES" = " " ] && ATADRIVES=""
   ATAOPTICALDRIVES="`echo "$ALLDRVS0" | grep '^sr' | tr '\n' ' '`"
   [ "$ATAOPTICALDRIVES" = " " ] && ATAOPTICALDRIVES=""
   if [ -e /proc/ide ];then
    for ONEIDE in `ls -1 /proc/ide | grep '^hd' | tr '\n' ' '`
    do
     if [ "`cat /proc/ide/${ONEIDE}/media`" = "cdrom" ];then
      ATAOPTICALDRIVES="${ATAOPTICALDRIVES}${ONEIDE} "
     else
      ATADRIVES="${ATADRIVES}${ONEIDE} "
     fi
    done
   fi
   ATADRIVES0="`echo -n "$ATADRIVES" | tr ' ' '\n'`"
   ATAOPTICALDRIVES0="`echo -n "$ATAOPTICALDRIVES" | tr ' ' '\n'`"
   echo '#ATADRIVES is all internal ide/pata/sata drives, excluding optical, excluding usb...' >> /etc/rc.d/PUPSTATE
   echo "ATADRIVES='${ATADRIVES}'" >> /etc/rc.d/PUPSTATE
   echo '#ATAOPTICALDRIVES is list of non-usb optical drives...'  >> /etc/rc.d/PUPSTATE #110206
   echo "ATAOPTICALDRIVES='$ATAOPTICALDRIVES'"  >> /etc/rc.d/PUPSTATE
 fi
fi

[ ! -d /proc/acpi ] && modprobe apm #load apm.ko if no acpi.
zcat /proc/config.gz | grep -q '^CONFIG_INPUT_LEDS=m' && modprobe input-leds #for >= k4.2x

### /var/local/xorg_udev is created when:
### - a touchscreen has been detected
### - missing xorg input-kbd and input-mouse drivers [ex: ubuntu xenial]
TOUCHMOD=`lsmod|grep touch`
#mavrothal: Check if it is an OLPC XO and add the devices...
ISITANXO=`cat /sys/class/dmi/id/product_name`
ISITAMAC=`grep -i '^Apple' /sys/class/dmi/id/board_vendor`
[ "$DISTRO_BINARY_COMPAT" = 'slackware64' ] && lsuffix=64 || lsuffix=
if [ ! -f /usr/lib${lsuffix}/xorg/modules/input/kbd_drv.so -a ! -f /usr/lib${lsuffix}/xorg/modules/input/mouse_drv.so ] ; then
  echo "Warning: Xorg kbd_drv.so and mouse_drv.so are missing"
  XORG_UDEV=1
fi

# this might cause side effects.. only use with xorg udev stuff
# see http://murga-linux.com/puppy/viewtopic.php?t=108017&start=345
if [ -n "$TOUCHMOD" -o -n "$ISITAMAC" -o "$ISITANXO" = "XO" -o "$XORG_UDEV" = '1' ] ; then
	udevadm trigger --action=add --subsystem-match="input" --subsystem-match="sound"
	udevadm settle
fi

TOUCHSCREEN="$(udevadm info --export-db | grep ID_INPUT_TOUCHSCREEN=1)"
if [ -n "$TOUCHSCREEN" ] ; then
  echo "Touchscreen detected: $TOUCHSCREEN"
  XORG_UDEV=1
else
  echo "No touchscreens detected"
fi
if [ -n "$ISITAMAC" ] ; then
  echo "MAC detected: $ISITAMAC"
  udevadm trigger --action=add --subsystem-match="power_supply"
  udevadm settle
  XORG_UDEV=1
fi
[ "$DISTRO_BINARY_COMPAT" = 'raspbian' ] && XORG_UDEV=1
if [ "$XORG_UDEV" = '1' ] ; then
  echo "Activating Xorg Evdev"
  [ ! -f /var/local/xorg_udev ] && rm -fv /etc/X11/xorg.conf #force xorgwizard-automatic
  touch /var/local/xorg_udev
else
  echo "Deactivating Xorg Evdev"
  [ -f /var/local/xorg_udev ] && rm -fv /etc/X11/xorg.conf #force xorgwizard-automatic
  rm -fv /var/local/xorg_udev
fi


status_func 0

#################MISC. SYSTEM SETUP#################
echo "MISC. SYSTEM SETUP"

echo -e "${DISTRO_NAME} Linux\n`uname -s` `uname -r` [`uname -m` arch]\n\n" > /etc/issue

# see https://www.frozentux.net/iptables-tutorial/other/ip_dynaddr.txt
# turn on special handling of dynamic addresses - quiet mode
echo "1" > /proc/sys/net/ipv4/ip_dynaddr

hostname -F /etc/hostname

################WAIT MODULES LOADED##################
echo "WAIT MODULES LOADED"
#previous module loading may not have completed...
echo -n "Waiting for modules to complete loading..." >/dev/console
PCMCIABUILTIN='no'
if [ "`modinfo yenta_socket 2>/dev/null`" = "" ];then   #Marvmod shut this up.
 #kernel has PCMCIA core drivers builtin.
 PCMCIABUILTIN='yes'
else
  WAITCNT=0
  PCIPCMCIA="`lspci -n | grep -o ' 0607: '`"
  if [ "$PCIPCMCIA" != "" ];then   #this may be slow to respond. 
   echo -n " pcmcia"  >/dev/console
   while [ $WAITCNT -lt 10 ];do
    [ "`lsmod | grep -E '^yenta_socket |^tcic |^i82092 |^i82365 |^pd6729 '`" != "" ] && break
    WAITCNT=`expr $WAITCNT + 1`
    sleep 1
    echo -n " $WAITCNT" >/dev/console
   done
  fi
fi

#note, if initrd then usb-storage will have already loaded...
USBBUILTIN='no'
if [ "`modinfo ehci_hcd 2>/dev/null`" = "" ];then #110712 shut this up.
 #kernel has usb core drivers (and usb-storage) builtin.
 USBBUILTIN='yes'
else
 PCIUSB="`lspci -n | grep -o -E ' 0c03: '`" #160609
 if [ "$PCIUSB" != "" ];then #this may be slow to respond.
  echo -n " usb"  >/dev/console
  PCIUSBNUM=`echo "$PCIUSB" | sort -u | wc -l`
  while [ $WAITCNT -lt 10 ];do
   [ `lsmod | grep -o -E '^uhci_hcd|^ohci_hcd|^ehci_hcd|^xhci_hcd' | wc -l` -ge $PCIUSBNUM ] && break #160609
   WAITCNT=`expr $WAITCNT + 1`
   sleep 1
   echo -n " $WAITCNT" >/dev/console
  done
 fi
fi

#110511 now using udevadm for usb, ssb and pcmcia... 110513 keep ssb as before...
#v424 try it a different way, this also fixes ssb devices (such as b43.ko)...
[ -e /sys/bus/ssb/devices ] && NEWSSB="`ls /sys/bus/ssb/devices/*/uevent 2>/dev/null | tr '\n' ' '`"
for ONEUEVENT in ${NEWSSB} #${NEWPCMCIA}${NEWUSB}${NEWSSB} #110511
do
  ONEPATH="`dirname $ONEUEVENT`"
  #the check for 'modalias' file is maybe needed for old kernel?...
  [ ! -e ${ONEPATH}/modalias ] && [ "`grep 'MODALIAS' $ONEUEVENT`" = "" ] && continue
  echo add > $ONEUEVENT
  sleep 0.02
done
#wasn't getting the right uevents for my 3g modem... i think need this:
udevadm trigger --action=add --subsystem-match="pcmcia*" --subsystem-match="usb*"

if [ "$USBBUILTIN" = "no" ];then #110712
 #wait for usb-storage drives to become available...(already done if initrd)
 #note, udevd logs to this file when load modules
 # (the latter via udev handler script /sbin/pup_event_backend_modprobe)...
 #101119 /tmp/pup_event_backend/pup_event_module_devpath_log* now multiple files (see /sbin/pup_event_backend_modprobe)
 if [ "`cat /tmp/pup_event_backend/pup_event_module_devpath_log* | grep 'usb_storage'`" != "" ];then #see pup_event_backend_modprobe
  echo -n " usb-storage"  >/dev/console
  while [ $WAITCNT -lt 15 ];do
   [ "`dmesg | grep 'usb-storage: device scan complete'`" != "" ] && break
   sleep 1
   WAITCNT=`expr $WAITCNT + 1`
   echo -n " $WAITCNT" >/dev/console
  done
  #precaution, make sure have got them all... need sort -u...
  USBSTORAGES=`dmesg | grep "usb-storage: device found at" | sort -u | wc -l`
  while [ $WAITCNT -lt 15 ];do
   AVAILABLEUSBSTORAGES=`dmesg | grep "usb-storage: device scan complete" | wc -l`
   [ $AVAILABLEUSBSTORAGES -ge $USBSTORAGES ] && break
   sleep 1
   WAITCNT=`expr $WAITCNT + 1`
   echo -n " $WAITCNT" >/dev/console
  done
 fi

 sleep 1 #v411 a bit extra. rerwin reports usb mouse detection problem some hardware.
         #(delay before usb mouse info appears in /proc/bus/input/devices)
fi

status_func 0

##############USER SELECTED MODULES##################
echo "USER SELECTED MODULES"
#the user can select extra modules to load in the BootManager...
if [ "$ADDLIST" != "" ];then #variable is in /etc/rc.d/MODULESCONFIG
 echo -n "Loading user-selected modules..." >/dev/console
 for MODULE in $ADDLIST
 do
  MPARAMS=""
  if [ `echo -n "$MODULE" | tr ':' ' ' | wc -w` -gt 1 ];then
   MPARAMS="`echo -n "$MODULE" | cut -f 2-9 -d ':' | tr ':' ' '`"
   MODULE="`echo -n "$MODULE" | cut -f 1 -d ':'`"
  fi
  echo -n " $MODULE" >/dev/console
  echo "Loading module $MODULE $MPARAMS"
  firmware_tarball_func #install firmware tarball.
  #for mwave.ko (modem), do not load module, just the firmware, which has script that correctly loads mwave.ko.
  [ "$MODULE" != "mwave" ] && modprobe $MODULE $MPARAMS
 done
 status_func 0
fi


###################SETUP SERVICES################
echo "SETUP SERVICES"
echo -n "Setting up services (network" >/dev/console
if [ -h /dev/modem ];then
 DEVM="`readlink /dev/modem`"
 case $DEVM in
  modem) #error, circular link.
   rm -f /dev/modem
   DEVM=""
  ;;
  /dev/*) #wrong format.
   DEVM="`echo -n "$DEVM" | cut -f 3,4 -d '/'`"
   ln -svnf $DEVM /dev/modem
  ;;
 esac
 case $DEVM in
  ttyS[0-9]) #apparently setserial can crash with other modems.
   setserial -v -b /dev/modem auto_irq skip_test autoconfig
  ;;
 esac
fi

#had hoped to retire this, but HardInfo, Pupscan need it... 110814 fix test...
[ -e /proc/bus/usb ] && busybox mount -t usbfs none /proc/bus/usb

#only needed for 2.6.21.7, as 2.6.25.x loads these automatically...
#explicitly load battery, ac, thermal, fan modules.
modprobe battery
if [ -z "$ISITAMAC" ];then #don't run this block on mac
 if [ -d /proc/acpi/battery ]; then
  results="`find /proc/acpi/battery -mindepth 1 -type d`"
  if [ ! -z "$results" ]; then
   modprobe ac
   modprobe thermal
   modprobe fan
  else
   rmmod battery
  fi
 fi
fi
#100814 100903 record cumulative tx/rx, see also network_tray and rc.shutdown...
UPDATE_MONTH="`date +%b`"
CURRENT_MONTH="`cat /var/local/sns/current_month`"
if [ "$UPDATE_MONTH" != "$CURRENT_MONTH" ];then
 echo "$UPDATE_MONTH" > /var/local/sns/current_month
 for ONECOUNT in sns/r sns/t pupdial/isp1/r pupdial/isp1/t pupdial/isp2/r pupdial/isp2/t;do
  echo -n 0 > /var/local/${ONECOUNT}x_bytes_month
 done
fi

#----------------------
sleep 5 # in some cases network modules take some time to load
network_default_connect #frisbee, sns, network wizard, pgprs-connect, pupdial, etc
#----------------------

echo -n ", printing, etc.)..." >/dev/console
#----------------------
/etc/rc.d/rc.services & #run scripts in /etc/rc.d/init.d
#----------------------
echo -e "\\033[64G\\033[1;33m[backgrounded]\\033[0;39m" >/dev/console #column 62, yellow. 110426: 64

############RECOGNISE MEDIA DEVICES################
echo "RECOGNISE MEDIA DEVICES"
STATUS=0
echo -n "Recognising media devices..." >/dev/console

echo -n ' optical' >/dev/console #optical drives
OPTCNT=1
CDTYPE="" ; DVDTYPE="" ; CDBURNERTYPE=""
OPTICALS="`grep '^drive name:' /proc/sys/dev/cdrom/info | grep -o -E 'sr.*|hd.*' | tr '\t' ' '`"
[ -L /dev/cdrom ] && CDTYPE="`readlink /dev/cdrom | cut -f 3 -d '/'`"
[ -L /dev/dvd ] && DVDTYPE="`readlink /dev/dvd | cut -f 3 -d '/'`"
[ -f /etc/cdburnerdevice ] && CDBURNERTYPE="`cat /etc/cdburnerdevice`"
[ "`echo "$OPTICALS" | grep "$CDTYPE"`" = "" ] && CDTYPE="" #no longer exists.
[ "`echo "$OPTICALS" | grep "$DVDTYPE"`" = "" ] && DVDTYPE="" #no longer exists.
[ "`echo "$OPTICALS" | grep "$CDBURNERTYPE"`" = "" ] && CDBURNERTYPE="" #no longer exists.
for ONEOPTICAL in $OPTICALS
do
 ONENUM="`echo -n "$ONEOPTICAL" | cut -c 3`"
 [ "$CDTYPE" = "" ] && CDTYPE="$ONEOPTICAL"
 [ "$DVDTYPE" = "" ] && [ "`grep '^Can read DVD' /proc/sys/dev/cdrom/info | head -n 1 | grep -o '[01].*' | sed -e 's/[^01]//g' | cut -c $OPTCNT`" = "1" ] && DVDTYPE="$ONEOPTICAL" #100131
 [ "$CDBURNERTYPE" = "" ] && [ "`grep '^Can write CD' /proc/sys/dev/cdrom/info | head -n 1 | grep -o '[01].*' | sed -e 's/[^01]//g' | cut -c $OPTCNT`" = "1" ] && CDBURNERTYPE="$ONEOPTICAL" #100131
 OPTCNT=`expr $OPTCNT + 1`
done
rm -f /dev/cdrom /dev/dvd /etc/cdburnerdevice
[ "$CDTYPE" ] && ln -sfv /dev/$CDTYPE /dev/cdrom
[ "$DVDTYPE" ] && ln -sfv /dev/$DVDTYPE /dev/dvd
[ "$CDBURNERTYPE" ] && echo -n "$CDBURNERTYPE" > /etc/cdburnerdevice

echo -n ' input' >/dev/console #input
if [ ! -s /etc/mousedevice ];then #120423 change -f to -s test.
 echo -n "input/mice" > /etc/mousedevice
 ln -snfv input/mice /dev/mouse
else
 [ "`cat /etc/mousedevice`" = "psaux" ] && echo -n "input/mice" > /etc/mousedevice
fi
#120423 pemasu: /dev/mouse was missing in full install...
MOUSELINK="`cat /etc/mousedevice`" #(refer /usr/sbin/input-wizard for examples)
if [ ! -e /dev/$MOUSELINK ];then #precaution, in case mouse interface is gone (unlikely, being paranoid).
 echo -n "input/mice" > /etc/mousedevice
 ln -snfv input/mice /dev/mouse
fi
[ ! -e /dev/mouse ] && ln -sv $MOUSELINK /dev/mouse

#---- rc.country
/etc/rc.d/rc.country

############MISC DESKTOP STUFF##################
echo "MISC. DESKTOP STUFF"
if [ -f /root/Choices/ROX-Filer/PuppyPin ] ; then
	if [ "$PUPMODE" = "77" ];then #77=multisession cd/dvd.
	 if [ "`cat /root/Choices/ROX-Filer/PuppyPin | grep "savesession"`" = "" ];then
	  echo '<icon x="768" y="128" label="save">/usr/sbin/savesession-dvd</icon>' >> /root/Choices/ROX-Filer/PuppyPin
	  grep -v '/pinboard' /root/Choices/ROX-Filer/PuppyPin  > /tmp/PuppyPin-CPY
	  cp -fv /tmp/PuppyPin-CPY /root/Choices/ROX-Filer/PuppyPin
	  echo '</pinboard>' >> /root/Choices/ROX-Filer/PuppyPin
	 fi
	else
	 sed -i '/savesession-dvd/d' /root/Choices/ROX-Filer/PuppyPin
	fi
	#save button on desktop when booted from flash drive...
	if [ $PUPMODE -eq 3 -o $PUPMODE -eq 7 -o $PUPMODE -eq 13 ];then #pup_rw is tmpfs.
	 if [ "`cat /root/Choices/ROX-Filer/PuppyPin | grep "save2flash"`" = "" ];then
	  echo '<icon x="768" y="128" label="save">/usr/sbin/save2flash</icon>' >> /root/Choices/ROX-Filer/PuppyPin
	  grep -v '/pinboard' /root/Choices/ROX-Filer/PuppyPin  > /tmp/PuppyPin-CPY
	  cp -fv /tmp/PuppyPin-CPY /root/Choices/ROX-Filer/PuppyPin
	  echo '</pinboard>' >> /root/Choices/ROX-Filer/PuppyPin
	 fi
	else
	 sed -i '/save2flash/d' /root/Choices/ROX-Filer/PuppyPin
	fi
fi
if [ "$PUPMODE" = "77" ];then #77=multisession cd/dvd.
	mkdir -p /root/Desktop
	echo '[Desktop Entry]
Encoding=UTF-8
Name=savesession-dvd
Exec=savesession-dvd
Terminal=false
Type=Application
Icon=/usr/share/pixmaps/puppy/save.svg' > /root/Desktop/savesession-dvd.desktop
else
	rm -f /root/Desktop/savesession-dvd.desktop
fi
if [ $PUPMODE -eq 3 -o $PUPMODE -eq 7 -o $PUPMODE -eq 13 ];then #pup_rw is tmpfs.
	mkdir -p /root/Desktop
	echo '[Desktop Entry]
Encoding=UTF-8
Name=save2flash
Exec=save2flash
Terminal=false
Type=Application
Icon=/usr/share/pixmaps/puppy/save.svg' > /root/Desktop/save2flash.desktop
else
	rm -f /root/Desktop/save2flash.desktop
fi

###################PERSONAL BOOT SCRIPT######################
echo "PERSONAL BOOT SCRIPT"
#personal boot script here...
if [ ! -f /etc/rc.d/rc.local ];then
 echo '#this file called from rc.sysinit' > /etc/rc.d/rc.local
 echo '#you can edit this file' >> /etc/rc.d/rc.local
 echo '#When firewall is installed, will append lines to this file...' >> /etc/rc.d/rc.local
fi
. /etc/rc.d/rc.local

#improper shutdown check. see above, also rc.shutdown and /sbin/init...
if [ ! -d /initrd ];then #if no /initrd, full hd install.
 [ ! $PDEV1 ] && PDEV1="`df | grep ' /$' | grep '^/dev/' | cut -f 1 -d ' ' | cut -f 3 -d '/'`"
 [ ! $DEV1FS ] && DEV1FS="`mount | grep ' on / ' | grep '^/dev/' | cut -f 5 -d ' '`"
 if [ "$PDEV1" -a "$DEV1FS" ];then
  [ "`grep '^PDEV1' /etc/rc.d/PUPSTATE`" = "" ] && echo "PDEV1='$PDEV1'" >> /etc/rc.d/PUPSTATE
  [ "`grep '^DEV1FS' /etc/rc.d/PUPSTATE`" = "" ] && echo "DEV1FS='$DEV1FS'" >> /etc/rc.d/PUPSTATE
  #this file gets removed by rc.shutdown if a proper shutdown...
  echo -n "${PDEV1},${DEV1FS}," > /fsckme.flg #ex: sda7,ext3,
  busybox chmod 666 /fsckme.flg #110503 so non-root can delete it.
 fi
else
 if [ "$PUPSAVE" ];then
  echo -n "$PUPSAVE" > /initrd${PUP_HOME}/fsckme.flg #ex: sda7,ext3,/pupsave-10MAR2010.2fs
  busybox chmod 666 /initrd${PUP_HOME}/fsckme.flg #110503 so non-root can delete it.
 fi
fi

if [ "$BOOT_SCHEDULER" ];then #120704 see /etc/rc.d/BOOTCONSTRAINED, variable set in 3builddistro.
 #my kernel defaults to 'cfq', change to 'deadline'. refer: http://tombuntu.com/index.php/2008/09/04/four-tweaks-for-using-linux-with-solid-state-drives/
 if [ "$PDEV1" ];then
  PDEV="`echo -n "$PDEV1" | sed -e 's%[0-9]*$%%' -e 's%p$%%'`" #mmcblk0p2 becomes mmcblk0
  if [ "`cat /sys/block/${PDEV}/queue/scheduler | grep "$BOOT_SCHEDULER"`" != "" ];then #check available.
   if [ "`cat /sys/block/${PDEV}/queue/scheduler | cut -f 2 -d '[' | cut -f 1 -d ']' | grep "$BOOT_SCHEDULER"`" = "" ];then #check not already chosen.
    echo $BOOT_SCHEDULER > /sys/block/${PDEV}/queue/scheduler
    echo 1 > /sys/block/${PDEV}/queue/iosched/fifo_batch
   fi
  fi
 fi
fi

# peebee work around for rfkill in some HP laptops
rfkill list | grep -q "yes" && rfkill unblock wlan

# SFR hack for IO bug http://murga-linux.com/puppy/viewtopic.php?p=681383#681383
KERNVER=${KERNVER%%-*} # just for appending "-4g","-PAE" or whatever
if [ ! "$PUPMODE" = 5 ];then  
  if vercmp $KERNVER ge 3.2 ;then
    if vercmp $KERNVER lt 3.8 ;then
      case "$DEV1FS" in ntfs|vfat|ext2|exfat) # changed 130210, SFR
        mount -o remount,sync /dev/loop1 ;;
      esac
    fi
  fi
fi

[ -f /var/tmp/initrd_full_install_flag ] && rm -f /var/tmp/initrd_full_install_flag

#that's it. next stop is /etc/profile...
###END###
